#include <stdio.h>
#include "stack.h"
#include <math.h>
#include "mystring.h"


/*!
 *  \fn mul
 *  \brief pulls two elements, multiplicates them and pushes result back into stack
 *  \param Stack is a pointer to a stack_t variable
 *  \return 0 if operation wasn't successful, 1 otherwise
 */

int mul(struct stack_t* stack);

/*!
 *  \fn sub
 *  \brief pulls two elements, substracts one from another and pushes result back into stack
 *  \param Stack is a pointer to a stack_t variable
 *  \return 0 if operation wasn't successful, 1 otherwise
 */

int sub(struct stack_t* stack);

/*!
 *  \fn add
 *  \brief pulls two elements, adds them and pushes result back into stack
 *  \param Stack is a pointer to a stack_t variable
 *  \return 0 if operation wasn't successful, 1 otherwise
 */
int add(struct stack_t* stack);

/*!
 *  \fn div
 *  \brief pulls two elements, divides one on another and pushes result back into stack
 *  \param Stack is a pointer to a stack_t variable
 *  \return 0 if operation wasn't successful, 1 otherwise
 */

int struct_div(struct stack_t* stack);

/*!
 *  \fn sqr
 *  \brief pulls one element, makes square from in and pushes result back into stack
 *  \param Stack is a pointer to a stack_t variable
 *  \return 0 if operation wasn't successful, 1 otherwise
 */
int sqr(struct stack_t* stack);

/*!
 *  \fn stack_sqrt
 *  \brief pulls one element, takes square root from it and pushes result back into stack
 *  \param Stack is a pointer to a stack_t variable
 *  \return 0 if operation wasn't successful, 1 otherwise
 */
int stack_sqrt(struct stack_t* stack);



int main()
{
    struct text Commands = FileToText("Commands.txt");
    struct stack_t stack = {};
    Stack_ctor(&stack, Commands.Lines);
    for (int i = 0; i < Commands.Lines; i++)
    {
        if (!strncmp(Commands.StringsArray[i], "add", sizeof("add") - 1))
        {
            add(&stack);
        }
        if (!strncmp(Commands.StringsArray[i], "mul", sizeof("mul") - 1))
        {
            mul(&stack);
        }
        if (!strncmp(Commands.StringsArray[i], "sub", sizeof("sub") - 1))
        {
            sub(&stack);
        }
        if (!strncmp(Commands.StringsArray[i], "div", sizeof("div") - 1))
        {
            struct_div(&stack);
        }
        if (!strncmp(Commands.StringsArray[i], "sqr", sizeof("sqr") - 1) && Commands.StringsArray[i][3] != 't')
        {
            sqr(&stack);
        }
        if (!strncmp(Commands.StringsArray[i], "sqrt", sizeof("sqrt") - 1))
        {
            stack_sqrt(&stack);
        }
        if (!strncmp(Commands.StringsArray[i], "push", sizeof("push") - 1))
        {
            double c = strtod(Commands.StringsArray[i] + sizeof("push"), NULL);
            Stack_push(&stack, c);
        }
        if (!strncmp(Commands.StringsArray[i], "pull", sizeof("pull") - 1))
        {
            double c = 0;
            Stack_pull(&stack, &c);
        }
    }

    Stack_dump(&stack);
    return 0;
}

int mul(struct stack_t* stack)
{
    double a = 0;
    double b = 0;
    if(Stack_pull(stack, &a) && Stack_pull(stack, &b))
    {
        double c = a * b;
        Stack_push(stack, c);
        return 1;
    }
    return 0;
}

int sub(struct stack_t* stack)
{
    double a = 0;
    double b = 0;
    if(Stack_pull(stack, &a) && Stack_pull(stack, &b))
    {
        double c = a - b;
        Stack_push(stack, c);
        return 1;
    }
    return 0;
}


int add(struct stack_t* stack)
{
    double a = 0;
    double b = 0;
    if(Stack_pull(stack, &a) && Stack_pull(stack, &b))
    {
        double c = a + b;
        Stack_push(stack, c);
        return 1;
    }
    return 0;
}

int struct_div(struct stack_t* stack)
{
    double a = 0;
    double b = 0;
    if(Stack_pull(stack, &a) && Stack_pull(stack, &b) && b)
    {
        double c = a/b;
        Stack_push(stack, c);
        return 1;
    }
    return 0;
}


int sqr(struct stack_t* stack)
{
    double a = 0;
    if(Stack_pull(stack, &a))
    {
        double c = a*a;
        Stack_push(stack, c);
        return 1;
    }
    return 0;
}

int stack_sqrt(struct stack_t* stack)
{
    double a = 0;
    if(Stack_pull(stack, &a) && a >= 0)
    {
        double c = sqrt(a);
        Stack_push(stack, c);
        return 1;
    }
    return 0;
}
